#if MIN_VERSION_unix(2,8,0)
let open = do
fd <- openFd (fromOsPath f) ReadOnly
- (defaultFileFlags { nofollow = True })
+ (defaultFileFlags { nofollow = True, cloexec = True })
fdToHandle fd
in bracket open hClose readhandle
#else
#ifndef mingw32_HOST_OS
git_annex <- fromOsPath <$> liftIO programPath
ps <- gitAnnexDaemonizeParams
- let logfd = openFdWithMode (toRawFilePath "/dev/null") ReadOnly Nothing defaultFileFlags
+ let logfd = openFdWithMode (toRawFilePath "/dev/null") ReadOnly Nothing
+ defaultFileFlags
+ (CloseOnExecFlag True)
liftIO $ daemonize git_annex ps logfd Nothing False runNonInteractive
#else
liftIO $ foreground Nothing runNonInteractive
#ifndef mingw32_HOST_OS
-- On unix, git simply uses O_EXCL
h <- openFdWithMode (fromOsPath lck) ReadWrite (Just 0O666)
-#if MIN_VERSION_unix(2,8,0)
- (defaultFileFlags { exclusive = True, cloexec = True })
-#else
- (defaultFileFlags { exclusive = True })
- setFdOption h CloseOnExec True
-#endif
+ (defaultFileFlags { exclusive = True }) (CloseOnExecFlag True)
#else
-- It's not entirely clear how git manages locking on Windows,
-- since it's buried in the portability layer, and different
docopynoncow iv = do
#ifndef mingw32_HOST_OS
let open = do
+ fd <- openFdWithMode f' ReadOnly Nothing
+ defaultFileFlags (CloseOnExecFlag True)
-- Need a duplicate fd for the post check.
- fd <- openFdWithMode f' ReadOnly Nothing defaultFileFlags
dupfd <- dup fd
+ setFdOption dupfd CloseOnExec True
h <- fdToHandle fd
return (h, dupfd)
let close (h, dupfd) = do
maybe noop lockPidFile pidfile
a
_ -> do
- nullfd <- openFdWithMode (toRawFilePath "/dev/null") ReadOnly Nothing defaultFileFlags
+ nullfd <- openFdWithMode (toRawFilePath "/dev/null") ReadOnly Nothing defaultFileFlags
+ (CloseOnExecFlag True)
redir nullfd stdInput
redirLog =<< openlogfd
environ <- getEnvironment
#endif
{- Locks the pid file, with an exclusive, non-blocking lock,
- - and leaves it locked on return.
+ - and leaves it locked on return. The lock file is not closed on exec, so
+ - when daemonize runs the process again, it inherits it.
-
- Writes the pid to the file, fully atomically.
- Fails if the pid file is already locked by another process. -}
lockPidFile pidfile = do
#ifndef mingw32_HOST_OS
fd <- openFdWithMode (fromOsPath pidfile) ReadWrite (Just stdFileMode) defaultFileFlags
+ (CloseOnExecFlag False)
locked <- catchMaybeIO $ setLock fd (WriteLock, AbsoluteSeek, 0, 0)
- fd' <- openFdWithMode (fromOsPath newfile) ReadWrite (Just stdFileMode) defaultFileFlags
- { trunc = True }
+ fd' <- openFdWithMode (fromOsPath newfile) ReadWrite (Just stdFileMode)
+ (defaultFileFlags { trunc = True })
+ (CloseOnExecFlag True)
locked' <- catchMaybeIO $ setLock fd' (WriteLock, AbsoluteSeek, 0, 0)
case (locked, locked') of
(Nothing, _) -> alreadyRunning
checkDaemon pidfile = bracket setup cleanup go
where
setup = catchMaybeIO $
- openFdWithMode (fromOsPath pidfile) ReadOnly (Just stdFileMode) defaultFileFlags
+ openFdWithMode (fromOsPath pidfile) ReadOnly
+ (Just stdFileMode)
+ defaultFileFlags
+ (CloseOnExecFlag True)
cleanup (Just fd) = closeFd fd
cleanup Nothing = return ()
go (Just fd) = catchDefaultIO Nothing $ do
Nothing -> walk c rest
Just info -> do
mfd <- catchMaybeIO $
- openFdWithMode (toRawFilePath dir) Posix.ReadOnly Nothing Posix.defaultFileFlags
+ openFdWithMode (toRawFilePath dir) Posix.ReadOnly Nothing
+ Posix.defaultFileFlags
+ (CloseOnExecFlag True)
case mfd of
Nothing -> walk c rest
Just fd -> do
let setup = do
fd <- openFdWithMode dest' WriteOnly
(Just $ combineModes readModes)
- (defaultFileFlags {exclusive = True})
+ (defaultFileFlags { exclusive = True })
+ (CloseOnExecFlag True)
fdToHandle fd
let cleanup = hClose
let go h = readFile (fromOsPath src) >>= hPutStr h
- License: BSD-2-clause
-}
-{-# LANGUAGE CPP #-}
-
module Utility.LockFile.Posix (
LockHandle,
lockShared,
-- Close on exec flag is set so child processes do not inherit the lock.
openLockFile :: LockRequest -> Maybe ModeSetter -> LockFile -> IO Fd
-openLockFile lockreq filemode lockfile = do
- l <- applyModeSetter filemode lockfile $ \filemode' ->
- openFdWithMode (fromOsPath lockfile) openfor filemode' $
-#if MIN_VERSION_unix(2,8,0)
- defaultFileFlags { cloexec = True }
-#else
- defaultFileFlags
- setFdOption l CloseOnExec True
-#endif
- return l
+openLockFile lockreq filemode lockfile =
+ applyModeSetter filemode lockfile $ \filemode' ->
+ openFdWithMode (fromOsPath lockfile) openfor filemode'
+ defaultFileFlags (CloseOnExecFlag True)
where
openfor = case lockreq of
ReadLock -> ReadOnly
{- openFd wrapper to support old versions of unix package.
-
- - Copyright 2023 Joey Hess <id@joeyh.name>
+ - Copyright 2023-2025 Joey Hess <id@joeyh.name>
-
- License: BSD-2-clause
-}
import Utility.RawFilePath
-openFdWithMode :: RawFilePath -> OpenMode -> Maybe FileMode -> OpenFileFlags -> IO Fd
+newtype CloseOnExecFlag = CloseOnExecFlag Bool
+
+openFdWithMode :: RawFilePath -> OpenMode -> Maybe FileMode -> OpenFileFlags -> CloseOnExecFlag -> IO Fd
+openFdWithMode f openmode filemode flags (CloseOnExecFlag closeonexec) = do
#if MIN_VERSION_unix(2,8,0)
-openFdWithMode f openmode filemode flags =
- openFd f openmode (flags { creat = filemode })
+ openFd f openmode (flags { creat = filemode, cloexec = closeonexec })
#else
-openFdWithMode = openFd
+ fd <- openFd f openmode filemode flags
+ when closeonexec $
+ setFdOption fd CloseOnExec True
+ return fd
#endif
#endif
-}
openFileBeingWritten :: RawFilePath -> IO Handle
openFileBeingWritten f = do
- fd <- openFdWithMode f ReadOnly Nothing defaultFileFlags
+ fd <- openFdWithMode f ReadOnly Nothing defaultFileFlags (CloseOnExecFlag True)
(fd', fdtype) <- mkFD (fromIntegral fd) ReadMode (Just (Stream, 0, 0)) False False
mkHandleFromFD fd' fdtype (fromRawFilePath f) ReadMode False Nothing
--- /dev/null
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 7"""
+ date="2025-09-04T19:42:44Z"
+ content="""
+I've checked all uses of openFd and made CloseOnExec be used where
+appropriate. Also checked all the fd dupping.
+
+This won't fix the problem, but is necessary goundwork for fixing
+openFile and the rest.
+"""]]